/**
 * *****************************************************************************
 * Copyright (c) 2012, G. Weirich and Elexis
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    G. Weirich - initial implementation
 * *****************************************************************************
 */

package ch.elexis.persistence.couchbase

import java.util.Map

import scala.collection.mutable.HashMap

import ch.elexis.core.data.IChangeListener
import ch.elexis.core.data.IPersistentObject
import ch.elexis.core.data.ISticker
import ch.elexis.core.data.IXid
import ch.elexis.core.data.Query
import ch.rgw.tools.StringTool

/**
 * The companion object for PersistentCouchObjects holds constants and global values
 */
object PersistentCouchObject {
  val FLD_ID = "__id__";
  val FLD_LASTUPDATE = "__lastupdate__"
  val FLD_DATUM = "__date__"
  val FLD_DELETED = "__deleted__"

  /**
   * this map holds all the attribute name/value pairs
   */
  private var fields = scala.collection.immutable.Map[String, String]()
  
  
  def addMapping(prefix: String, fielddefs: String*) = {
    fielddefs.foreach(s => {
      val fn = s.split("\\s*=\\s*")
      if (fn.length == 2) {
        fields += (prefix + fn(0) -> fn(1))
      } else {
        fields += (prefix + fn(0) -> fn(0))
      }
    })
  }
}

/**
 * The base class for PersistentObjects stored in a document oriented database.
 */
class PersistentCouchObject extends IPersistentObject with Serializable {
  import PersistentCouchObject._

  PersistentCouchObject.addMapping("PersistentCouchObject", FLD_ID, FLD_LASTUPDATE, FLD_DATUM, FLD_DELETED)

   /**
   * this map holds a copy of the key this object is encrypted with for each
   * partner who is allowed to decode the object. The key is encrypted with
   * each partner's certificate separately. If encrypted persistence is selected,
   * at least one entry - the entry for our own certificate - must be present.
   */
  var keychain = scala.collection.immutable.Map[String,String]()

  private val properties = HashMap[String, String]()
  private[couchbase] var cas = 0L

  override def create(uid: String) = {
    set(FLD_ID,if (uid == null) StringTool.unique("PCO") else uid);
    PersistentCouchManager.store(this)
    true
  }

  private[couchbase] def setCAS(newCas: Long) = cas = newCas
  private[couchbase] def getCas = cas

  /**
   * save this Object to the backing store
   * TODO: define failure
   */
  def flush = PersistentCouchManager.store(this)

  override def getLabel(): String = getId()

  override def isValid(): Boolean = (cas > 0L) && (getId.length() > 0)

  override def getId(): String = get(FLD_ID)

  override def storeToString(): String = { null }

  override def state(): Int = { 0 }

  override def exists(): Boolean = { false }

  override def isAvailable(): Boolean = { false }

  override def getXid(domain: String): String = { null }

  override def getXid() = null

  override def getXids() = null

  override def addXid(domain: String, domain_id: String, updateIfExists: Boolean): Boolean = { false }

  override def setExtended(obj: IPersistentObject, bWaitUntilFinished: Boolean) = Unit

  override def getExtended(xid: IXid) = null

  override def listExtended(xidDomain: String) = null //List[Array[String]]

  override def removeExtended(xid: IXid, bWaitUntilFinished: Boolean) = Unit

  override def getStickers() = null

  override def getSticker() = null

  override def removeSticker(st: ISticker): Unit = {}

  override def addSticker(et: ISticker): Unit = {}

  override def isDeleted(): Boolean = { false }

  override def isDragOK(): Boolean = { false }

  override def get(field: String): String = { null }

  override def getMap(field: String) = null

  override def getInt(field: String): Int = { 0 }

  override def set(field: String, value: String): Boolean = {
    properties.put(field, value)
    true
  }

  override def setMap(field: String, map: java.util.Map[Object, Object]): Unit = {}

  override def setInt(field: String, value: Int): Boolean = { false }

  override def set(fields: Array[String], values: Array[String]): Boolean = { false }

  override def get(fields: Array[String], values: Array[String]): Boolean = { false }

  override def getLastUpdate(): Long = { 0L }

  override def addChangeListener(cl: IChangeListener, propertyObserved: String) = Unit

  override def removeChangeListener(cl: IChangeListener, propertyObserved: String) = Unit

  override def isMatching(obj: IPersistentObject, mode: Int, fields: String*) = false

  override def isMatching(query: java.util.List[Query.Term]) = false

  override def isMatching(fields: Array[String], mode: Int, others: String*) = false

  override def isMatching(fields: Map[String, String], mode: Int, bSkipIfInexisting: Boolean) = false

}